#include "tcpclient.h"
#include "./ui_tcpclient.h"
#include<QFile>
#include<QByteArray>
#include<QDebug>
#include<QMessageBox>
#include<QHostAddress>
#include<QTcpSocket>
#include<QAbstractSocket>
#include"protocol.h"
#include<QDataStream>
#include"operaterwidget.h"

TcpClient::TcpClient(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::TcpClient)
{

    this->resize(500,300);
    ui->setupUi(this);



    //调用配置文件的函数，读取配置的Ip + Port
    this->loadConfig();

    //信号与槽函数进行处理,m_tcpSocket 对象发出连接的信号，TcpClient进行处理
    connect(&m_tcpSocket,&QTcpSocket::connected,this,&TcpClient::showConnect);

    //信号与槽函数进行处理,m_tcpSocket 对象接收连接的信号，TcpClient进行处理
    connect(&m_tcpSocket,&QTcpSocket::readyRead,this,&TcpClient::recvMsg);


    //m_tcpSocket ,通过 m_tcpSocket 对象进行服务器链接
    m_tcpSocket.connectToHost(QHostAddress(m_strIP),m_usPort);

}

TcpClient::~TcpClient()
{
    delete ui;
}

void TcpClient::loadConfig()
{
    qDebug()<<"TcpClient::loadConfig :"<<Qt::endl;
    //实现 读取配置文件，并加载，QFile 加载文件
    //定义一个 file 对象
    QFile file(":/config.config");
    //以只读的方式进行打开
    if(file.open(QIODevice::ReadOnly)){
        //文件读取成功
        // 文件读取
        QByteArray baData=file.readAll();
        //字节数据转为 字符串数据,数据转为 Char*
        QString strData=baData.toStdString().c_str();
        //文件关闭
        file.close();

        QStringList strList=strData.split("\r\n");

        m_strIP=strList.at(0);
        m_usPort=strList.at(1).toUShort();

        qDebug()<<"IP :"<< m_strIP<<Qt::endl;
        qDebug()<<"PORT :"<< m_usPort<<Qt::endl;


    }else{
        //文件读取失败
        QMessageBox::critical(this,"open cofig","open config failed");
    }

}

TcpClient &TcpClient::getInstance()
{
    static TcpClient instance;
    return instance;
}

QTcpSocket &TcpClient::getTcpSocket()
{
    return m_tcpSocket;
}

void TcpClient::showConnect()
{
    // 实现  m_tcpSocket 链接服务器的 槽函数
    QMessageBox::information(this,"TcpClient connected server","TcpClient connected server success");
}

void TcpClient::recvMsg()
{
    //客户端接收数据信号与槽函数
    qDebug()<<"bytesAvailable is : "<<m_tcpSocket.bytesAvailable();
    //处理接收的数据协议单元
    //先接收四个字节，uiPDUlen,包含了整个数据协议单元的长度

    uint uiPDUlen=0;
    //read 方法接收数据
    m_tcpSocket.read((char *)(&uiPDUlen),sizeof(uint));

    qDebug()<<"uiPDUlen"<<uiPDUlen;

    //数据真实长度是 数据协议总长度 - PDU结构体占用大小
    uint uiMsglen=uiPDUlen-sizeof(PDU);

    PDU *pdu=mkPDU(uiMsglen);

    //接收剩余的字节数据,偏移 uiPDUlen , (char *)pdu，表示pdu数据地址
    m_tcpSocket.read((char *)pdu+sizeof(uint),uiPDUlen-sizeof(uint));

    qDebug()<<"uiMsgType recvMsg is : "<<pdu->uiMsgType<<"caMsg recvMsg is : "<<(char *)(pdu->caData);

    //获取消息类型，和接收的 caData数据，caData数据在注册时存放了用户名和密码，字节长度为32位
    //根据不同的消息类型，对应进行操作
    switch (pdu->uiMsgType) {
    case ENUM_MSG_TYPE_REGIST_RESPOND:
    {

        qDebug()<<"TYPE_REGIST_RESPOND";
        if(0==strcmp(pdu->caData,REGIST_OK))
        {
            QMessageBox::information(this,"regist",REGIST_OK);
            qDebug()<<REGIST_OK;
        }
        else if(0==strcmp(pdu->caData,REGIST_FAILED))
        {
            qDebug()<<REGIST_FAILED;
            QMessageBox::warning(this,"regist",REGIST_FAILED);
        }
        break;
    }
    case ENUM_MSG_TYPE_LOGIN_RESPOND:
    {

        qDebug()<<"TYPE_LOGIN_RESPOND";
        if(0==strcmp(pdu->caData,LOGIN_OK))
        {
            QMessageBox::information(this,"login",LOGIN_OK);
            qDebug()<<REGIST_OK;

            //登录成功，跳转操作主页面
            OperaterWidget::getInstance().show();
        }
        else if(0==strcmp(pdu->caData,LOGIN_FAILED))
        {
            qDebug()<<REGIST_FAILED;
            QMessageBox::warning(this,"login",LOGIN_FAILED);
        }
        break;
    }
    default:
        break;
    }

    free(pdu);
    pdu=NULL;
}

#if 0
void TcpClient::on_send_pb_clicked()
{
    //获取文本
    QString strMsg=ui->lineEdit->text();


    if(!strMsg.isEmpty()){
        //采用自定义的数据协议单元，申请空间
        PDU * pdu=mkPDU(strMsg.size());
        pdu->uiMsgType=8888;

        //在协议数据单元，储存数据，strcpy 或者 memcpy
        memcpy(pdu->caMsg,strMsg.toStdString().c_str(),pdu->uiMsglen);

        //发送数据
        m_tcpSocket.write((char *)pdu,pdu->uiPDUlen);
        //发送完成后
        // 清空数据
        free(pdu);
        pdu=NULL;


    }else {
        //数据为空
        QMessageBox::warning(this,"Msg is NULL","Msg is NULL, Please check!!");
    }

}

#endif

void TcpClient::on_login_pb_clicked()
{

    //获取用户名和密码
    QString strUserName =ui->name_le->text();
    QString strPwd =ui->pwd_le->text();

    if(!strUserName.isEmpty() || ! strPwd.isEmpty()){

        //注册不需要消息，消息长度为0
        PDU *pdu =mkPDU(0);
        pdu->uiMsgType=ENUM_MSG_TYPE_LOGIN_REQUEST;

        //数据存放
        strncpy(pdu->caData,strUserName.toStdString().c_str(),32);
        strncpy(pdu->caData+32,strPwd.toStdString().c_str(),32);

        //发送数据
        m_tcpSocket.write((char *)pdu,pdu->uiPDUlen);
        //发送完成后
        // 清空数据
        free(pdu);
        pdu=NULL;
    }
    else {
        QMessageBox::critical(this,"Login","Login failed ， the UserName or Password is NUll");
    }

}


void TcpClient::on_register_pb_clicked()
{
    //获取用户名和密码
    QString strUserName =ui->name_le->text();
    QString strPwd =ui->pwd_le->text();

    if(!strUserName.isEmpty() || ! strPwd.isEmpty()){

        //注册不需要消息，消息长度为0
        PDU *pdu =mkPDU(0);
        pdu->uiMsgType=ENUM_MSG_TYPE_REGIST_REQUEST;

        //数据存放
        strncpy(pdu->caData,strUserName.toStdString().c_str(),32);
        strncpy(pdu->caData+32,strPwd.toStdString().c_str(),32);

        //发送数据
        m_tcpSocket.write((char *)pdu,pdu->uiPDUlen);
        //发送完成后
        // 清空数据
        free(pdu);
        pdu=NULL;


    }else {
        QMessageBox::critical(this,"Regist","Regist failed ， the UserName or Password is NUll");
    }

}


void TcpClient::on_cancell_pb_clicked()
{

}

